﻿// (c) Copyright Damian Mehers http://damianblog.com/
// This source is subject to the Microsoft Public License.
// See http://www.microsoft.com/resources/sharedsource/licensingbasics/sharedsourcelicenses.mspx.
// All other rights reserved.

using System;
using System.Diagnostics;
using System.Threading;
using System.Windows.Forms;
using WMPLib;
using Microsoft.MediaCenter.Hosting;

namespace MceFM.Last.MediaPlayer {
  public partial class MediaPlayerForm : Form {
    private RemotedWindowsMediaPlayer remotedWindowsMediaPlayer;
    private WindowsMediaPlayer windowsMediaPlayer;

    //internal event EventHandler<NewSongPlayingEventArgs> NewSongPlaying;
//    internal event EventHandler<TrackTimeEventArgs> TrackTime;
    internal event EventHandler<TrackStoppedOrStartedEventArgs> TrackStoppedOrStarted;


    public MediaPlayerForm() {
      InitializeComponent();
    }



    private void MediaPlayerInfo_Load(object sender, EventArgs e) {
      InitializedWindowsMediaPlayer();
    }

    private bool InitializedWindowsMediaPlayer() {
      lock (this) {
        if(windowsMediaPlayer != null) return true;

        if(!Util.IsWindowsMediaPlayerRunning()) return false;

        try {

          remotedWindowsMediaPlayer = new RemotedWindowsMediaPlayer();
          for(int i = 0;i < 10;i++) {
            try {
              Controls.Add(remotedWindowsMediaPlayer);
              break;
            } catch(Exception ex) {
              Trace.TraceError("Error adding RemotedWIndowsMedia Player: {0}", ex);
              Thread.Sleep(500);
            }
          }
          windowsMediaPlayer = (WindowsMediaPlayer)remotedWindowsMediaPlayer.GetOcx();
//          windowsMediaPlayer.CurrentItemChange += CurrentItemChanged;
          Trace.TraceInformation("Initialized WMP");
          return true;
        } catch(Exception ex) {
          Trace.TraceInformation(string.Format("Error creating RemotedWindowsMediaPlayer: {0}", ex));
          return false;
        }
      }
    }

    //private void CurrentItemChanged(object pdispMedia) {
    //  IWMPMedia wmpMedia = pdispMedia as IWMPMedia;
    //  if(wmpMedia == null) {
    //    return;
    //  }
    //  EventHandler<NewSongPlayingEventArgs> tmp = NewSongPlaying;
    //  if(tmp != null) {
    //    NewSongPlayingEventArgs newSongPlayingEventArgs = new NewSongPlayingEventArgs(wmpMedia.name, windowsMediaPlayer.URL);
    //    tmp(this, newSongPlayingEventArgs);
    //  }
    //  Trace.TraceInformation("Current Item Changed {0}", wmpMedia.name);
    //}

    private delegate void QueueUrlDelegate(string url, bool first);

    private void PrivateQueueUrl(string url, bool first) {
      try {
        IWMPMedia media = windowsMediaPlayer.newMedia(url);
        if(first) {
          Trace.TraceInformation("Queuing {0} (first song)", url);
          windowsMediaPlayer.URL = url;
        } else {
          Trace.TraceInformation("Queuing {0} (already playing)", url);
          windowsMediaPlayer.currentPlaylist.appendItem(media);
        }
      } catch(Exception ex) {
        Trace.TraceError("Error queueing up {0}: {1}", url, ex);
      }
    }

    public void QueueUrl(string url, bool first) {
      if (InitializedWindowsMediaPlayer()) {
        Invoke(new QueueUrlDelegate(PrivateQueueUrl), url, first);
      }
    }


    public void Next() {
      if (InitializedWindowsMediaPlayer()) {
        AddInHost.Current.MediaCenterEnvironment.MediaExperience.Transport.SkipForward();
      }
    }


    public void StopPlaying() {
      if (InitializedWindowsMediaPlayer()) {
        Invoke(new StopPlayingDelegate(PrivateStopPlaying));
      }
    }

    private delegate void StopPlayingDelegate();

    private void PrivateStopPlaying() {
      try {
        windowsMediaPlayer.controls.stop();
      } catch (Exception ex) {
        Trace.TraceError("Error asking Windows Media Player to stop: {0}", ex);
      }
    }
    
    
    private int previousElapsedTime = -1;
    private string previousTitle = "";
    private string previousAlbum = "";
    private string previousArtist = "";

    private void DurationTimer_Tick(object sender, EventArgs e) {
      if (!InitializedWindowsMediaPlayer()) {
        return;
      }

      try {
        // Can't do this since my extender does not update current position for streamed tracks
        // int elapsedTime = (int)windowsMediaPlayer.controls.currentPosition;
        IWMPMedia media = windowsMediaPlayer.controls.currentItem;
        if(media == null) {
//           Trace.TraceInformation("MediaPlayerInfo.DurationTimer_Tick but no media");
          return;
        }

        string title = media.name;
        string artist = media.getItemInfo("WM/AlbumArtist");
        string album = media.getItemInfo("WM/AlbumTitle");
        int duration = (int)media.duration;


        // Trace.TraceInformation("MediaPlayerInfo.DurationTimer_Tick Title is {0}, Artist is {1} and album is {2}", title, artist, album);

        WMPPlayState playState = windowsMediaPlayer.playState;

        if(playState == WMPPlayState.wmppsStopped || playState == WMPPlayState.wmppsMediaEnded || playState == WMPPlayState.wmppsUndefined) {
          // Trace.TraceInformation("MediaPlayerInfo.DurationTimer_Tick but stopped for {0}", title);
          if(previousArtist != null) {
            // Send a 'Stopped' message
            OnTrackStoppedOrStarted(new TrackStoppedOrStartedEventArgs(false, previousTitle, previousAlbum, previousArtist, previousElapsedTime, duration));
          }
          previousTitle = previousAlbum = previousArtist = null;
          previousElapsedTime = -1;
          return;
        }

        // If we are paused then do nothing
        if(playState == WMPPlayState.wmppsPaused) {
          Trace.TraceInformation("MediaPlayerInfo.DurationTimer_Tick but paused for {0}", title);
          return;
        }


        int elapsedTime;

        if(title != previousTitle || previousArtist != artist || previousAlbum != album) {
          if(previousTitle != null) {
            OnTrackStoppedOrStarted(new TrackStoppedOrStartedEventArgs(false, previousTitle, previousAlbum, previousArtist, previousElapsedTime, duration));
          }
          OnTrackStoppedOrStarted(new TrackStoppedOrStartedEventArgs(true, title, album, artist, duration));
          Trace.TraceInformation("MediaPlayerInfo.DurationTimer_Tick.  Title changed from {0} to {1}",
                                 previousTitle,
                                 title);
          elapsedTime = 0;
        } else {
          elapsedTime = previousElapsedTime + 1; // One second has gone by (timer is tiggered every second or so)
          //Trace.TraceInformation("MediaPlayerInfo.DurationTimer_Tick.  Title {0} elapsedTime is now {1} PlayState is {2}",
          //                       title,
          //                       elapsedTime,
          //                       playState);
//          OnTrackTimeChanged(new TrackTimeEventArgs(elapsedTime, title, windowsMediaPlayer.URL));
        }


        previousTitle = title;
        previousArtist = artist;
        previousAlbum = album;
        previousElapsedTime = elapsedTime;
      } catch(Exception ex) {
        Trace.TraceError("Error handing DurationTimer_Tick: {0}", ex);
      }

    }

    private void OnTrackStoppedOrStarted(TrackStoppedOrStartedEventArgs args) {
      EventHandler<TrackStoppedOrStartedEventArgs> tmp = TrackStoppedOrStarted;
      if (tmp != null) {
        tmp(this, args);
      }
    }

    //private void OnTrackTimeChanged(TrackTimeEventArgs args) {
    //  EventHandler<TrackTimeEventArgs> tmp = TrackTime;
    //  if(tmp != null) {
    //    tmp(this, args);
    //  }
    //}

  }
}